//
// Created by QU on 24-9-25.
//

#include <boost/asio.hpp>

#include <iostream>
#include <random>
#include <chrono>
#include <thread>
#include <MsgNode/Node.h>

using boost::asio::ip::tcp;

class SimpleClient
{
public:
    SimpleClient(boost::asio::io_context& io_context, const std::string& host, const std::string& port,
                 uint16_t payload_size)
        : socket_(io_context), payload_size_(payload_size), random_engine_(std::random_device { }())
    {
        tcp::resolver resolver(io_context);
        auto endpoints = resolver.resolve(host, port);
        boost::asio::connect(socket_, endpoints);
        std::cout << "Connected to " << host << ":" << port << std::endl;
    }

    void send_random_data()
    {
        std::uniform_int_distribution<> type_dist(0, 255);
        std::uniform_int_distribution<> id_dist(0, 255);

        uint8_t type_tag = type_dist(random_engine_);
        uint8_t msg_id = id_dist(random_engine_);

        Node node(payload_size_, type_tag, msg_id);

        // Generate random payload
        std::vector<uint8_t> payload(payload_size_);
        std::uniform_int_distribution<> byte_dist(0, 255);
        std::generate(payload.begin(), payload.end(), [&]() { return byte_dist(random_engine_); });
        node.setPayload(reinterpret_cast<const std::byte*>(payload.data()), payload_size_);

        auto serialized_data = node.serialize();
        std::cout << "[debug] SendBuffer size: " << node.getNodeFullSize() << std::endl;
        boost::asio::write(socket_, boost::asio::buffer(serialized_data.buffer.get(), serialized_data.length));

        std::cout << "Sent data: Type Tag = " << static_cast<int>(type_tag)
            << ", Message ID = " << static_cast<int>(msg_id)
            << ", Payload Size = " << payload_size_ << " bytes" << std::endl;
        std::cout << node;
    }

private:
    tcp::socket socket_;
    uint16_t payload_size_;
    std::mt19937 random_engine_;
};

int main(int argc, char* argv[])
{
    if (argc != 4)
    {
        std::cerr << "Usage: client <host> <port> <payload_size>" << std::endl;
        return 1;
    }

    try
    {
        boost::asio::io_context io_context;

        std::string host = argv[1];
        std::string port = argv[2];
        uint16_t payload_size = static_cast<uint16_t>(std::stoi(argv[3]));

        SimpleClient client(io_context, host, port, payload_size);

        for (int i = 0; i < 1000; ++i)
        {
            client.send_random_data();
            std::this_thread::sleep_for(std::chrono::milliseconds(10)); // 每秒发送一次数据
        }
    }
    catch (std::exception& e)
    {
        std::cerr << "Exception: " << e.what() << std::endl;
    }

    return 0;
}
